using System;
using System.Web;
using System.Web.Caching;

namespace EasyComm.Caching
{
    /// <summary>
    /// </summary>
    /// <remarks></remarks>
    /// <example></example>
    public class WebCache : ICache
    {
        #region private int? _expirationMinutes
        /// <summary>
        /// 
        /// Get/Sets the _expirationMinutes of the <see cref="UI.WebCommon.Caching.WebCache"/>
        /// </summary>
        private int? _expirationMinutes;
        #endregion

        #region public WebCache(int? expirationMinutes)
        /// <summary>
        /// Initializes a new instance of the <b>WebCache</b> class.
        /// </summary>
        /// <param name="expirationMinutes">Number of minutes items are kept since they were last accessed</param>
        public WebCache(int? expirationMinutes)
        {
            if (HttpContext.Current == null)
            {
                throw new ApplicationException("No HttpContext context");
            }
            if (!expirationMinutes.HasValue)
            {
                expirationMinutes = 1440;
            }
            _expirationMinutes = expirationMinutes;
        }
        #endregion

        #region protected System.Web.Caching.Cache CurrentCache
        /// <summary>
        /// Gets the CurrentCache of the WebCache
        /// </summary>
        /// <value></value>
        protected System.Web.Caching.Cache CurrentCache
        {
            get { return HttpContext.Current.Cache; }
        }
        #endregion

        #region public void AddItem(string key, object item)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="item"></param>
        public void AddItem(string key, object item)
        {
            this.AddItem(key, item, null, null);
        }
        #endregion

        #region public void AddItem(string key, object item, TimeSpan? expireTime, CacheItemRemovedCallback removedCallBack)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="item"></param>
        /// <param name="expireTime"></param>
        /// <param name="removedCallBack"></param>
        public void AddItem(string key, object item, TimeSpan? expireTime, CacheItemRemovedCallback removedCallBack)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            if (expireTime == null)
            {
                this.CurrentCache.Insert(key, item, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, _expirationMinutes.Value, 0), System.Web.Caching.CacheItemPriority.Normal, removedCallBack);
            }
            else
            {
                this.CurrentCache.Insert(key, item, null, System.Web.Caching.Cache.NoAbsoluteExpiration, expireTime.Value, System.Web.Caching.CacheItemPriority.Normal, removedCallBack);
            }
            while (this.CurrentCache[key] == null)
            {
                //_log.InfoFormat("WebCache: AddItem() Adding failed. key: {0}. Trying again.", key);
                System.Threading.Thread.Sleep(100);
                if (expireTime == null)
                {
                    this.CurrentCache.Insert(key, item, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, _expirationMinutes.Value, 0), System.Web.Caching.CacheItemPriority.Normal, removedCallBack);
                }
                else
                {
                    this.CurrentCache.Insert(key, item, null, System.Web.Caching.Cache.NoAbsoluteExpiration, expireTime.Value, System.Web.Caching.CacheItemPriority.Normal, removedCallBack);
                }
            }
            //_log.InfoFormat("WebCache: AddItem() Adding done. key: {0}.", key);
            //if (this.CurrentCache[key] == null)
            //{
            //    //_log.InfoFormat("WebCache: AddItem failed. key:{0}",key);
            //    throw new ServiceException("WebCache: AddItem failed.");
            //}
        }
        #endregion

        #region public bool RemoveItem(string key)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool RemoveItem(string key)
        {
            object existing = this.CurrentCache.Remove(key);
            return (existing != null);
        }
        #endregion

        #region public object GetItem(string key)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public object GetItem(string key)
        {
            object item = CurrentCache[key];
            if (item == null)
            {
                //_log.InfoFormat("WebCache: GetItem() Item not found. key: {0}.", key);
            }
            else
            {
                //_log.InfoFormat("WebCache: GetItem() Item found. key: {0}.", key);
            }
            return item;
        }
        #endregion

        #region public bool UpdateItem(string key, object value)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool UpdateItem(string key, object value)
        {
            object item = CurrentCache[key];
            if (item == null)
            {
                return false;
                //_log.InfoFormat("WebCache: GetItem() Item not found. key: {0}.", key);
            }
            else
            {
                CurrentCache[key] = value;
                return true;
                //_log.InfoFormat("WebCache: GetItem() Item found. key: {0}.", key);
            }
        }
        #endregion
    }
}
